#include <stdio.h>
#include <stdlib.h>

void case1()
{
    // 访问了一个超越界内存区域
    int *p = malloc(sizeof(int) * 100);
    p[100000] = 100;
}

int case2()
{
    /** 覆盖了动态分配内存区之前的区域 */
    int *p = (int*)malloc(sizeof(int) * 5);
    // 不小心通过指针q覆盖了动态分配的内存区域之前的区域
    int *q = p;
    q = q - 2;
    *q = 0;
    free(p);
    return 0;
}

int case3_func_with_problem(int *arr, int len)
{
    /** 因为一些程序错误，下标计算有误，超过了数组下标的有效范围*/
    int *q = arr - 1;
    printf("q=%lu\n", (unsigned long)q);
    *q = 1234567;
    return 3;
}

int case3()
{
    int arr[100] = {0};
    // 利用另一个函数对arr数组进行操作
    int val = 0;
    int ret = 0;
    printf("&val = %lu\n", (unsigned long)&val);
    printf("val = %d, ret = %d\n", val, ret);
    //printf("&val=%p\n", &val);
    ret = case3_func_with_problem(arr, 100);
    printf("val = %d, ret = %d\n", val, ret);
    return 3;
}

int case4()
{
    /** 通过指针不小心覆盖为函数调用关键内存区 */
    int arr[5] = {0};
    int *p = arr;
    // 因为一些错误计算，p指针指向超过了arr的范围
    p = arr + 9;
    // 对这些越界内存区域进行了修改
    *p = 0;
    printf("现在要从case4函数中返回\n");
    return 0;
}

void wild_pointer1()
{
    char *p;
    {
        char c;
        p = &c;
    }
    *p = '\0';
}

void wild_pointer2()
{
    char *p = (char *)malloc(1000000);
    free(p);
    printf("指针p已释放\n");
    *p = '\0';
    printf("访问已释放的内存区域\n");
}

void double_free()
{
    char *p = (char*)malloc(100000);
    printf("申请内存完毕\n");
    free(p);
    printf("第一次释放p\n");
    free(p);
    printf("第二次释放p\n");
}


int main(int argc, char **argv)
{
    /* case1情况：访问越界内存区域*/
    // case1();
    /* case2情况：覆盖了动态分配内存区前的内存区域 */
    //case2();
    /* case3情况：越界的指针变量修改了不该修改的内存区域 */
    //case3();
    /* case4情况：越界指针变量修改了函数调用关键返回区 */
    //case4();
    //printf("已经从case4函数返回\n");
    // wild_pointer1();
    // wild_pointer2();
    double_free();
    return 0;
}